package cn.schoolwow.quickserver.controller;

import cn.schoolwow.quickserver.controller.annotation.*;
import cn.schoolwow.quickserver.domain.MultipartFile;
import cn.schoolwow.quickserver.dto.User;
import cn.schoolwow.quickserver.request.HttpRequest;
import cn.schoolwow.quickserver.response.EventSource;
import cn.schoolwow.quickserver.response.HttpResponse;
import cn.schoolwow.quickserver.response.HttpStatus;
import cn.schoolwow.quickserver.session.HttpSession;
import org.junit.Assert;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpCookie;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

@RestController
public class IndexController {
    @RequestMapping(value = "/charset",method = RequestMethod.POST)
    public void charset(
            @RequestBody String data,
            HttpRequest httpRequest
    ) {
        Assert.assertEquals("这是一段GBK编码的文字",data);
        Assert.assertEquals("GBK",httpRequest.charset());
    }

    @RequestMapping("/pathVariable/{name}")
    public String pathVariable(
            @PathVariable(name = "name") String name
    ){
        return name;
    }

    @RequestMapping("/requestParam")
    public String requestParam(
            @RequestParam(name = "name") String name
    ){
        return name;
    }

    @RequestMapping("/requestParamPattern")
    public String requestParamPattern(
            @RequestParam(name = "today",pattern = "yyyy-MM-dd") LocalDate today
    ){
        return today.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    @RequestMapping(value = "/requestPart",method = RequestMethod.POST)
    public void requestPart(
            @RequestPart(name = "name") String name,
            @RequestPart(name = "defaultValue",required = false, defaultValue = "") String defaultValue
    ){
        Assert.assertEquals("value",name);
        Assert.assertEquals("",defaultValue);
    }

    @RequestMapping(value = "/uploadFile",method = RequestMethod.POST)
    public void uploadFile(
            @RequestPart(name = "file") MultipartFile multipartFile
    ){
        Assert.assertEquals("pom.xml",multipartFile.originalFilename);
    }

    @RequestMapping(value = "/uploadFiles",method = RequestMethod.POST)
    public void uploadFiles(
            @RequestPart(name = "files") MultipartFile[] multipartFiles
    ){
        Assert.assertEquals(2,multipartFiles.length);
        Assert.assertEquals("pom.xml",multipartFiles[0].originalFilename);
        Assert.assertEquals("README.md",multipartFiles[1].originalFilename);
    }

    @RequestMapping("/requestHeader")
    public String requestHeader(
            @RequestHeader(name = "name") String requestHeader
    ){
        return requestHeader;
    }

    @RequestMapping("/cookieValue")
    public String cookieValue(
            @CookieValue(name = "name") String cookieValue
    ){
        return cookieValue;
    }

    @RequestMapping("/sessionValue")
    public String sessionValue(
            @RequestHeader(name = "name",required = false,defaultValue = "") String requestHeader,
            @SessionValue(name = "sessionValue",required = false,defaultValue = "") String sessionValue,
            HttpSession httpSession
    ){
        if(null==sessionValue||sessionValue.isEmpty()){
            //第一次请求
            Assert.assertEquals("sessionValue",requestHeader);
            httpSession.getAttributes().put("sessionValue",requestHeader);
            return requestHeader;
        }else{
            //第二次请求
            Assert.assertEquals("sessionValue",sessionValue);
            return sessionValue;
        }
    }

    @RequestMapping("/compositeParameter")
    public String compositeParameter(
            User user
    ){
        return user.getUsername();
    }

    @RequestMapping(value = "/requestBodyString",method = RequestMethod.POST)
    public String requestBodyString(@RequestBody String data){
        return data;
    }

    @RequestMapping(value = "/requestBodyJSON",method = RequestMethod.POST)
    public User requestBodyJSON(@RequestBody User user){
        return user;
    }

    @RequestMapping(value = "/requestBodyArray",method = RequestMethod.POST)
    public int requestBodyJSON(@RequestBody List<User> users){
        return users.size();
    }

    @RequestMapping(value = "/multipartFile",method = RequestMethod.POST)
    public long multipartFile(
            @RequestPart(name = "name") String name,
            @RequestPart(name = "file") MultipartFile file
    ){
        return file.size;
    }

    @RequestMapping("/basicAuth")
    @BasicAuth(username = "quickserver",password = "123456")
    public void basicAuth(){}

    @RequestMapping(value = "/crossOrigin")
    @CrossOrigin
    public void crossOrigin(){}

    @RequestMapping("/httpRequest")
    public void httpRequest(
            HttpRequest httpRequest
    ){
        Assert.assertEquals("127.0.0.1",httpRequest.ip());
        Assert.assertEquals("GET",httpRequest.method());
        Assert.assertEquals("/httpRequest",httpRequest.uri().toString());
        Assert.assertEquals("HTTP/1.1",httpRequest.protocol());
        Assert.assertEquals("utf-8",httpRequest.charset());
    }

    @RequestMapping("/httpResponse")
    public void httpResponse(
            HttpResponse httpResponse
    ){
        httpResponse.status(HttpStatus.OK);
        httpResponse.setHeader("testSetHeader","OK");
        httpResponse.addHeader("testAddHeader","OK1");
        httpResponse.addHeader("testAddHeader","OK2");
        httpResponse.charset("utf-8");
        httpResponse.addCookie(new HttpCookie("testCookie","testCookieValue"));
    }

    @RequestMapping("/httpSession")
    public String httpSession(
            HttpSession httpSession
    ){
        return httpSession.getId();
    }

    @RequestMapping("/streamingBody")
    public void streamingBody(
            HttpResponse httpResponse
    ) throws IOException {
        for(int i=0;i<3;i++){
            OutputStream outputStream = httpResponse.getOutputStream();
            outputStream.write(("data"+i+"\n").getBytes(httpResponse.getCharset()));
            outputStream.flush();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @RequestMapping("/eventSource")
    public void eventSource(
            HttpResponse httpResponse
    ) throws IOException {
        for(int i=0;i<3;i++){
            httpResponse.eventSource(new EventSource(i,"message","data"+i));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @RequestMapping("/redirect")
    public String redirect() {
        return "redirect:/requestParam?name=redirect";
    }

    @RequestMapping(value = "/uploadRequestBody",method = RequestMethod.POST)
    public int uploadRequestBody(
            HttpRequest httpRequest
    ) {
        return httpRequest.getBodyAsBytes().length;
    }

    @RequestMapping(value = "/keepAlive")
    public void uploadRequestBody(
            @RequestParam(name = "parameter") String parameter,
            HttpRequest httpRequest,
            HttpResponse httpResponse
    ) {
        System.out.println(new String(httpRequest.getBodyAsBytes()));
    }

    @RequestMapping(value = "/exceptionHandler")
    public void exceptionHandler(
    ) throws IOException {
        throw new IOException("异常测试");
    }
}
